--
-- Author: shunguo.chen
-- Date: 2018-11-09 14:18:24
--
-- TeamTargetVo 队伍目标信息

local SpeedDungeonInfo = import(".SpeedDungeonInfo")

local fileName = string.getModeName(...)
local ClassRef = class(fileName)

-- 1.每个副本都有开放等级，添加一个低等级副本概念：
--     40级以前，副本等级低于玩家等级达到30级时（包括30）为低等级副本。
--     40级以后，副本等级低于玩家等级达到30级时（包括30）为低等级副本。
local LOW_TARGET_TYPE_LV = 40
local LOW_TARGET_LV_1 = 100
local LOW_TARGET_LV_2 = 100

local PVP_REWARD_KEYS = {
    "victoryReward",
    "goldCupReward",
    "silverCupReward",
    "copperCupReward",
    "failureReward"
}
local PVP_REWARD_KEY_NAMES = {
    L("ui_csd_675"),
    L("ashes_trophy_gold"),
    L("ashes_trophy_silver"),
    L("ashes_trophy_bronze"),
    L("ui_csd_86")
}

function ClassRef:ctor(data)
    if data then
        self:init(data)
    end
end

-- data = teamTarget conf
function ClassRef:init(data) 
    self._conf = data

    self.id = tonumber(data.ID)
    self.type = tonumber(data.type)
    self.openLv = tonumber(data.openLv)
    self._quickMatch = tonumber(data.quickMatch or 0)

    self._isAutoRecruit = false
    self._isAutoApply = false

    -- 玩法是否开放
    self._isOpen = false

    self.subTargets = {}
    self.curSubTargets = {}

    if self:isSpeed() then
        -- 竞速副本添加竞速信息
        local initData = {target=self.id, sec=0, rewarded="NONE"}
        self._speedInfo = SpeedDungeonInfo.new(initData)
    elseif self:isPvp() then
        self._challengeInfo = nil
    end

    -- 每天奖励次数除了读取配置，地下城副本还会从UD里面设置
    -- 这是配置表中的奖励次数
    self.rewardNum = tonumber(data.num)
    self.restRewardNum = self.rewardNum

    -- 每周奖励次数
    self.weeklyRewardNum = 0
    self.weeklyRestRewardNum = 0

    -- 跨服匹配
    self._isInCrossMatch = false
end

-- 打开该目标的匹配界面的参数
function ClassRef:getTeamMatchParams()
    return {targetId=self.id}
end

-- 是否有每日奖励次数限制
function ClassRef:isRewardNumLimit()
    return self.rewardNum > 0
end

-- 是否有每周奖励次数限制
function ClassRef:isWeeklyRewardNumLimit()
    return self.weeklyRewardNum > 0
end

-- 设置副本次数数据
-- message DungeonRemainTimes{
--  int32 ID = 1;   //副本ID
--  int32 DailyTimes = 2;
--  int32 DailyLimit = 3;
--  int32 WeeklyTimes = 4;
--  int32 WeeklyLimit = 5;
-- }
function ClassRef:setDungeonTimes(dungeonTimes)
    -- dump(dungeonTimes, "setDungeonTimes " .. self.id)
    -- if dungeonTimes.WeeklyTimes < dungeonTimes.DailyTimes and dungeonTimes.WeeklyLimit > 0 then
    --     printError("setDungeonTimes error")
    -- end
    -- 每周奖励次数
    self.weeklyRewardNum = dungeonTimes.WeeklyLimit
    self.weeklyRestRewardNum = dungeonTimes.WeeklyTimes

    -- 每日奖励次数
    self.rewardNum = dungeonTimes.DailyLimit
    if dungeonTimes.WeeklyLimit > 0 then
        self.restRewardNum = math.min(dungeonTimes.DailyTimes, dungeonTimes.WeeklyTimes)
    else
        self.restRewardNum = dungeonTimes.DailyTimes
    end
end

-- 跨天了，客户端主动修正一下次数
function ClassRef:onDailyUpdate(isWeekChange)
    if isWeekChange then
        self.weeklyRestRewardNum = self.weeklyRewardNum
    end
    if self.weeklyRewardNum > 0 then
        self.restRewardNum = math.min(self.rewardNum, self.weeklyRestRewardNum)
    else
        self.restRewardNum = self.rewardNum
    end
end

-- 每日剩余奖励次数
function ClassRef:getRewardNum()
    return self.rewardNum
end
function ClassRef:setRestRewardNum(num)
    self.restRewardNum = num
end
function ClassRef:getRestRewardNum()
    return self.restRewardNum
end

-- 每周剩余奖励次数
function ClassRef:getWeeklyRewardNum()
    return self.weeklyRewardNum
end
function ClassRef:setWeeklyRestRewardNum(num)
    self.weeklyRestRewardNum = num
end
function ClassRef:getWeeklyRestRewardNum()
    return self.weeklyRestRewardNum
end

-- 组队玩法的大类型 Enums.TeamMatchType
-- 对应teamTarget_type中type字段
function ClassRef:setTeamMatchType(tp)
    self.teamMatchType = tp
end
function ClassRef:getTeamMatchType()
    return self.teamMatchType
end

-- 设置是否跨服匹配中
function ClassRef:setIsInCrossMatch(b)
    self._isInCrossMatch = b
end
function ClassRef:isInCrossMatch(isRecursive)
    -- TeamTarget即可作为二级菜单又可作为三级菜单, 递归且有下级菜单时才考虑子项
    if isRecursive and #self.curSubTargets > 0 then
        -- 多个目标的，有一个子目标是自动招募即可
        local isAuto = false
        for i,target in ipairs(self.curSubTargets) do
            if target == self then
                isAuto = isAuto or self._isInCrossMatch
            else
                isAuto = isAuto or target:isInCrossMatch(true)
            end
            if isAuto then
                break
            end
        end
        return isAuto
    end
    return self._isInCrossMatch
end

-- 自动招募（组队 只有一个）
function ClassRef:setAutoRecruit(b)
    self._isAutoRecruit = b
end
function ClassRef:isAutoRecruit(isRecursive)
    -- TeamTarget即可作为二级菜单又可作为三级菜单, 递归且有下级菜单时才考虑子项
    if isRecursive and #self.curSubTargets > 0 then
        -- 多个目标的，有一个子目标是自动招募即可
        local isAuto = false
        for i,target in ipairs(self.curSubTargets) do
            if target == self then
                isAuto = isAuto or self._isAutoRecruit
            else
                isAuto = isAuto or target:isAutoRecruit(true)
            end
            if isAuto then
                break
            end
        end
        return isAuto
    end
    return self._isAutoRecruit
end

-- 自动申请（非组队 有多个）
function ClassRef:setAutoApply(b)
    self._isAutoApply= b
end
function ClassRef:isAutoApply(isRecursive)
    -- TeamTarget即可作为二级菜单又可作为三级菜单, 递归且有下级菜单时才考虑子项
    if isRecursive and #self.curSubTargets > 0 then
        -- 多个目标的，有一个子目标是自动招募即可
        local isAuto = false
        for i,target in ipairs(self.curSubTargets) do
            if target == self then
                isAuto = isAuto or self._isAutoApply
            else
                isAuto = isAuto or target:isAutoApply(true)
            end
            if isAuto then
                break
            end
        end
        return isAuto
    end
    return self._isAutoApply
end

-- 全部子目标，只在Enums.TeamTargetType.normal/Enums.TeamTargetType.legion 时有
function ClassRef:setSubTargets(targets)
    self.subTargets = targets
end

-- 当前子目标，只在Enums.TeamTargetType.normal/Enums.TeamTargetType.legion 时有
function ClassRef:setCurSubTargets(targets)
    self.curSubTargets = targets
end

-- 更新竞速副本信息
function ClassRef:updateSpeedInfo(info)
    self._speedInfo:init(info)
end

-- 获得竞速副本信息
function ClassRef:getSpeedInfo()
    return self._speedInfo
end

-- 缓存挑战信息
function ClassRef:setChallengeInfo(info)
    self._challengeInfo = info
end
function ClassRef:getChallengeInfo()
    return self._challengeInfo
end

-- 目录结构是三层结构
function ClassRef:isThreeLayer()
    return self:isNormal() or self:isLegion()
end

-- 是普通地下城 5人
function ClassRef:isNormal()
    return self.type == Enums.TeamTargetType.normal
end

-- 是团队地下城 10人
function ClassRef:isLegion()
    return self.type == Enums.TeamTargetType.legion
end

-- 是竞速副本
function ClassRef:isSpeed()
    return self.type == Enums.TeamTargetType.speed
end

-- 是秘境副本
function ClassRef:isSecret()
    return self.type == Enums.TeamTargetType.secret
end

-- 是锦标赛
function ClassRef:isPvp()
    return self.type == Enums.TeamTargetType.pvp
end

-- 是活动副本
function ClassRef:isActivity()
    return self.type == Enums.TeamTargetType.activity
end

-- 是训练副本
function ClassRef:isTraining()
    return self.id == Enums.TeamTarget.training
end

-- 是世界boss副本
function ClassRef:isWorldBoss()
    return self.id == Enums.TeamTarget.worldBoss
end

-- 是野外boss
function ClassRef:isWildBoss()
    return self.id == Enums.TeamTarget.wildBoss
end

-- 是剧情副本
function ClassRef:isStoryTask()
    return self.id == Enums.TeamTarget.storyTask
end

-- 是灰烬入侵
function ClassRef:isGrayBattle()
    return self.id == Enums.TeamTarget.ashInvade
end

-- 是精英竞技场
function ClassRef:isEliteMatch()
    return self.id == Enums.TeamTarget.eliteMatchArena
end

-- 是精英赛
function ClassRef:isElite()
    return self.id == Enums.TeamTarget.eliteMatchArena or self.id == Enums.TeamTarget.eliteMatchDuel
end

-- 是挑战赛
function ClassRef:isChallenge()
    return self.id == Enums.TeamTarget.challenge
end

-- 野外boss召唤数据
function ClassRef:setWildBossData(data)
    self._wildBossData = data
end
function ClassRef:getWildBossData()
    return self._wildBossData
end

-- 是否开启(配置表层面)
function ClassRef:isConfOpen(withReason)
    return UD:isMainTaskAndLvMeet(self._conf.taskId, self.openLv, withReason)
end

-- 是否开放（加上了业务逻辑）
function ClassRef:isOpen(onlySelf)
    -- TeamTarget即可作为二级菜单又可作为三级菜单, 不是自己且有下级菜单时才考虑子项
    if not onlySelf and #self.curSubTargets > 0 then
        -- 多个目标的，有一个子目标是开放即可
        local isOpen = false
        for i,target in ipairs(self.curSubTargets) do
            if target == self then
                isOpen = auto or self._isOpen
            else
                isOpen = isOpen or target:isOpen()
            end
            if isOpen then
                break
            end
        end
        return isOpen
    end
    return self._isOpen
end
function ClassRef:setIsOpen(b)
    self._isOpen = b
end

function ClassRef:getOpenLv()
    return self.openLv
end

function ClassRef:getId()
    return self.id
end

-- Enums.TeamTargetType 目标类型
function ClassRef:getType()
    return self.type
end

-- 是低级副本(只针对小队模式)
function ClassRef:isLowTarget(lv)
    if self:isNormal() then
        lv = lv or UD:getLevel()
        if lv <= LOW_TARGET_TYPE_LV then
            return (lv - self.openLv) >= LOW_TARGET_LV_1
        else
            return (lv - self.openLv) >= LOW_TARGET_LV_2
        end
    end
    return false
end

-- 是否快速匹配
function ClassRef:isQuickMatch()
    return self._quickMatch > 0
end

-- 快速匹配-跨服匹配
function ClassRef:isQuickCrossMatch()
    return self._quickMatch == 1
end

-- 快速匹配-强制匹配
function ClassRef:isQuickForceMatch()
    return self._quickMatch == 2
end

-- 是否单人玩法
function ClassRef:isSingle()
    return self._conf.maxNum == "1"
end

-- 是否任何时候都可以加入副本
function ClassRef:isCanJoinAnyStatus()
    return self._conf.disorder == "1"
end

-- 对战类型，1（pve）2（pvp）
function ClassRef:getVSType()
    return tonumber(self._conf.vsType)
end

-- 是pve类型
function ClassRef:isPveType()
    return self:getVSType() == 1
end

function ClassRef:getDungeonId()
    return tonumber(self._conf.dungeonId)
end
function ClassRef:getDungeonSubId()
    return tonumber(self._conf.dungeonSubId)
end

function ClassRef:getMenuIcon()
    if not self._menuIcon then
        self._menuIcon = string.format(Res.TeamTargetPath, self._conf.picturePath)
    end
    return self._menuIcon
end

-- 跨服匹配时是否禁止
function ClassRef:isForbidInCross()
    return self._conf.forbidInCross == "1"
end

-- 目标类型名字 竞速／天梯...
function ClassRef:setTypeName(name)
    self.typeName = name
end
function ClassRef:getTypeName()
    if self:isStoryTask() then
        return L("lua_code_text_437")
    elseif self:isElite() then
        return L("CrossServerEliteTab")
    elseif self:isChallenge() then
        return L("targetname23")
    else
        return L(self.typeName)
    end
end

function ClassRef:getBanner(isOpen)
    if not self._openBanner then
        local conf = GD:queryTeamTargetSurfaceById(self.id)
        self._openBanner = string.format("%s%s.png", Res.teamtarget_pic, conf.banner)
        self._closeBanner = string.format("%s%s.png", Res.teamtarget_pic, conf.unopenbanner)
    end
    isOpen = isOpen or self:isOpen()
    return isOpen and self._openBanner or self._closeBanner
end

function ClassRef:getName()
    return L(self._conf.name)
end

function ClassRef:getNameWithDiff()
    local name = self:getName()
    if self._conf.name2 then
        name = name .. "-" .. L(self._conf.name2)
    end
    return name
end

function ClassRef:getDifficultyName()
    if self:isLegion() then
        return L(self._conf.name2 or "") .. L("task_road_desc1")
    else
        return L(self._conf.name2 or "")
    end
end

-- 返回 竞速模式-幽魂城堡
function ClassRef:getFullName()
    if self:isSecret() then
        return string.format(L("teamtarget_secret_name"), SecretManager.info.layer)
    elseif self:isElite() then
        return L("CrossServerEliteTab") .. "-" .. L(self._conf.name)
    elseif self:isStoryTask() then
        return L("lua_code_text_84")
    else
        return self:getTypeName() .. "-" .. L(self._conf.name)
    end
end

-- 返回 竞速模式-幽魂城堡
function ClassRef:getFullNameWithDiff()
    local name = self:getFullName()
    if self._conf.name2 then
        name = name .. "-" .. L(self._conf.name2)
    end
    return name
end

-- 返回匹配追踪name 幽魂城堡(竞速)
function ClassRef:getTaskTrackName()
    local name = self:getName()
    if self._conf.name3 then
        name = string.format("%s(%s)", name, L(self._conf.name3))
    end
    return name
end

function ClassRef:getTeamReqStr()
    local str
    if self:isSecret() then
        str = table.concat({"teamtarget_secret_name", SecretManager.info.layer}, ",")
    elseif self:isEliteMatch() then
        str = table.concat({L("%s-%s"), "EliteMatchTip48", self._conf.name}, ",")
    else
        if self._conf.name2 then
            str = table.concat({L("%s-%s-%s"), self:getTypeName(), self._conf.name, self:getDifficultyName()}, ",")
        else
            str = table.concat({L("%s-%s"), self:getTypeName(), self._conf.name}, ",")
        end
    end
    return str
end

function ClassRef:getDesc()
    return L(self._conf.desc)
end

function ClassRef:getIcon()
    if not self._icon then
        self._icon = string.format(Res.TeamTargetPath, self._conf.iconPath)
    end
    return self._icon
end

-- 数值类型 1.普通 2.平衡 3.适配
function ClassRef:getNumType()
    return tonumber(self._conf.numericalType)
end

-- 是平衡模式
function ClassRef:isBalanceNumType()
    return self._conf.numericalType == "2"
end

-- 进入副本是是否需要确认人数
function ClassRef:needCheckNum()
    local isSingle = self:isSingle()
    local isQuickMatch = self:isQuickMatch()

    return not (isSingle or isQuickMatch or self._conf.numericalType == "3")
end

-- 数值类型icon
function ClassRef:getNumTypeIcon()
    if not self._numTypeIcon then
        local ary = {Res.teamUIPath, "team_star_", self._conf.numericalType, ".png"}
        self._numTypeIcon = table.concat(ary)
    end
    return self._numTypeIcon
end
-- 数值类型描述
function ClassRef:getNumTypeDesc()
    return L(self._conf.tips or "")
end
-- 推荐战力
function ClassRef:getCombat()
    if self:isSecret() then
        -- 秘境需要根据层数做修正
        local rate = SecretManager:getCurrentPowerRevise()
        return math.ceil(checknumber(self._conf.powerNeed) * rate / 10000)
    elseif self:isWorldBoss() then
        -- 世界Boss需要动态改变
        local extraNum = GD:getWorldBossDifficultyRevise()
        return math.ceil(checknumber(self._conf.powerNeed) + extraNum)
    else
        return checknumber(self._conf.powerNeed)
    end
end

-- 推荐平均战力，推荐战力／maxNum／1.2，千位四舍五入取整
function ClassRef:getAverageCombat()
    local combat = self:getCombat()
    local maxNum = self:getMaxNum()
    local average = math.ceil(combat/maxNum/1.2)
    local result = math.floor(average/1000)
    local remainder = average % 1000
    if remainder >= 500 then
        result = result + 1
    end
    return result * 1000
end

-- 队伍最大人数
function ClassRef:getMaxNum()
    return tonumber(self._conf.maxNum)
end

-- 是否可以带随从
function ClassRef:isWithPartner()
    return self._conf.partner == "1"
end

-- 排行榜id
function ClassRef:getRank()
    if self._conf.rank then
        return tonumber(self._conf.rank)
    end
end

-- 挑战赛 排行str
function ClassRef:getRankStr()
    if self:isPvp() then
        local challengeConf = GD:getChallengeInfo(self.id)
        local challengeInfo = self._challengeInfo
        local rankId = self:getRank()
        local rankConf = GD:getRankingConfigById(rankId)
        local myRank = challengeInfo.myRank
        local rankStr
        if challengeInfo.winTimes <= 0 or myRank <= 0 or myRank > tonumber(rankInfo.limit) then
            rankStr = L("bossRank_notOnTheList")
        else
            rankStr = string.format(L(challengeConf.rankShow), challengeInfo.winTimes, myRank)
        end
        return rankStr
    end
end

-- 获得奖励
function ClassRef:getRewards()
    if not self._rewards then
        if self:isPvp() then
            -- pvp 挑战赛
            -- local pvpInfo = app:sendMsg("PvpModel", "getPvpInfo")
            -- return pvpInfo:getRewards(self.id)
            local rewards = {}
            local challengeConf = GD:getChallengeInfo(self.id)
            for i,key in ipairs(PVP_REWARD_KEYS) do
                local value = challengeConf[key]
                if value then
                    local item = UD:parseRewardToBagItem(value)
                    local colorId = "gold"
                    if key == "victoryReward" then
                        colorId = "green"
                    elseif key == "failureReward" then
                        colorId = "blue"
                    end
                    rewards[#rewards + 1] = {item=item, name=PVP_REWARD_KEY_NAMES[i], colorId=colorId}
                end
            end
            self._rewards = rewards
        elseif self:isActivity() then
            local rewards = {}
            local conf = GD:queryEventModeById( self.id )
            local rewardStr, reward

            -- 活动要加上金、银、铜杯的活动点数
            for i=3,1,-1 do
                rewardStr = conf["reward" .. i]
                if rewardStr then
                    reward = UD:parseRewardToBagItem(rewardStr)
                    if reward then
                        rewards[#rewards + 1] = reward
                    end
                else
                    break
                end
            end

            -- 除活动点数额外的奖励
            rewardStr = conf.dropShow
            if rewardStr then
                local items = UD:parseItemsFromString(rewardStr)
                rewards = table.attach(rewards, items)
            end
            self._rewards = rewards
        elseif self:isSpeed() then
            self._rewards = {}
        else
            local rewards = {}
            if not self:isLowTarget() then
                rewards = UD:parseItemsFromString(self._conf.rewards)
            end
            local dungeonPoint = self._conf.dungeonPoint
            if dungeonPoint then
                local Daibi = require("app.public.dao.Daibi")
                local firstReward = Daibi.new()
                firstReward:read({tid=Enums.lootType.dungeonPoint, amount=tonumber(dungeonPoint)})
                table.insert(rewards, 1, firstReward)
            end
            self._rewards = rewards
        end
    end
    -- 普通副本，有可能在等级提升之后就变成低级副本而不需要显示道具掉落了，若如此，只取第一个奖励
    if self:isLowTarget() and self:isNormal() and #self._rewards > 1 then
        self._rewards = {self._rewards[1]}
    end
    return self._rewards
end

-- 检查开放情况，以及开放结束时间
function ClassRef:checkTimeOpen()
    -- 开启时间未填或者是"0"，全开放
    local openTime = self._conf.openTime
    if openTime == nil or openTime == "0" then
        return true
    end 

    if self._conf.refreshType == "1" then
        if not self._openTimeAry then
            -- 11:30-12:30;18:00-19:00
            local openTime = self._conf.openTime
            self._openTimeAry = string.splitThrice(openTime, {";", "-", ":"}, true)
        end

        local curTime = math.floor(app:getServerTime())
        local curDate = os.date("*t", curTime)
        local second = curDate.sec
        local curValue = curDate.hour * 60 + curDate.min
        local isOpen = false
        local refreshGap = 0
        local aryLen = #self._openTimeAry
        local startValue, endValue
        for i,ary in ipairs(self._openTimeAry) do
            startValue = ary[1][1] * 60 + ary[1][2]
            endValue = ary[2][1] * 60 + ary[2][2]
            if i == aryLen and curValue >= endValue then
                -- 最后一项还没有现在的大，就在第一天的基础上加一天
                ary = self._openTimeAry[1]
                startValue = ary[1][1] * 60 + ary[1][2] + 1440
                endValue = ary[2][1] * 60 + ary[2][2] + 1440
            end

            if curValue < startValue then
                isOpen = false
                refreshGap = (startValue - curValue) * 60 - second
                break
            elseif curValue >= startValue and curValue < endValue then
                isOpen = true
                refreshGap = (endValue - curValue) * 60 - second
                break
            end
        end

        return isOpen, refreshGap
    elseif self._conf.refreshType == "2" then
        -- TODO csg 按周开放，暂时没有
        return true
    else
        return true
    end
end


return ClassRef